/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */
 
#ifndef INTMAP_H_
#define INTMAP_H_

#ifdef __cplusplus
extern "C" {
#endif

/*
 * intmap provides a two way mapping of integers.
 * This is particularly useful for abstract 
 * lookups and TypeMaps.  As Argot performs a lot
 * of integer mappings this provides a quick and
 * small solution.
 * 
 * The current implementation does not allow
 * duplicates for the key.  It does however not
 * check for duplicates for the value.  This would
 * allow multiple values for the same key.  It
 * will also have unreliable results for performing
 * a backward search on a value.  This may be
 * changed in the future.
 * 
 * 
 */

struct intmap_item
{
	unsigned int key;
	unsigned int value;
	unsigned int hash_f;
	unsigned int hash_b;

	struct intmap_item * next_f;
	struct intmap_item * next_b;
};

typedef struct intmap_item intmap_item;

typedef struct intmap
{
	struct intmap_item ** table_f;  /* array of items */
	struct intmap_item ** table_b;
	unsigned int table_size;
	unsigned int count;   /* items in map */
	unsigned int mask;    /* mask used for table */

	struct intmap_item * current;
} intmap;

typedef struct intmap * pintmap;

#define intmap_rc int

#define INTMAP_OK  0
#define INTMAP_ERROR -1

void intmap_init( intmap * map, int powersize );

intmap *intmap_create( int powersize );
void intmap_destroy( intmap * im );
void intmap_clear( intmap * im );

intmap_rc intmap_find( intmap * im, int key );
intmap_rc intmap_find_key( intmap * im, int value );
intmap_rc intmap_add( intmap * im, int key, int value );
intmap_rc intmap_remove( intmap * im );


#define intmap_value(im) ((im)->current->value)
#define intmap_key(im) ((im)->current->key)
#define intmap_size(im) ((im)->count)

/*
 * Helper macros to retun value or -1
 */
#define intmap_find_value(im,key) (intmap_find((im),(key))==INTMAP_OK?(im)->current->value:-1)
#define intmap_find_key_value(im,value) (intmap_find_key((im),(value))==INTMAP_OK?(im)->current->key:-1)

typedef struct intmap_iterator
{
	intmap * map;
	intmap_item * current;
	int index;
}
intmap_iterator;

void intmap_iterator_init(intmap_iterator * imi, intmap * im);
int intmap_iterator_key(intmap_iterator * imi );
bool intmap_iterator_next( intmap_iterator * imi );


#ifdef __cplusplus
} /* end extern "C" */
#endif

#endif /*INTMAP_H_*/
